package com.suse.common.util.jwt;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import com.suse.common.util.core.StringUtil;
import com.suse.common.util.date.DateUtil;
import io.jsonwebtoken.*;

import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * JWT工具类
 * </p>
 *
 * @author 辜玉彬
 * @since 2022-08-18 22:21
 */
public class JwtUtil {

    /**
     * 创建 token
     * @return token
     */
    public static String createToken(Object object) {
        // Jwt 建造者 建造者模式
        JwtBuilder builder = Jwts.builder();
        // 第一部分: header 头
        builder.setHeaderParam("alg","HS256");
        builder.setHeaderParam("typ","JWT");
        // 第二部分: playload 有效载荷
        builder.setId(UUID.randomUUID().toString());
        // 公有字段
        builder.setSubject("zxjy-user");
        builder.setIssuedAt(new Date());
        // 过期时间
        if (StringUtil.isNotEmpty(JwtConstant.EXPIRE_DAYS)) {
            long expireDays = Long.parseLong(JwtConstant.EXPIRE_DAYS);
            LocalDateTime localDateTime = LocalDateTime.now().plusDays(expireDays);
            builder.setExpiration(DateUtil.date(localDateTime));
        }
        // 私有字段
        Map<String, Object> claims = getClaims(object);
        builder.setClaims(claims);
        // 第三部分: 签名哈希
        builder.signWith(SignatureAlgorithm.HS256, JwtConstant.SIGNING_KEY);
        // 连接
        return builder.compact();
    }

    /**
     * 解析 token
     * 解析失败返回 null
     * @param token token
     * @param type 结果类型
     * @param <T> 结果泛型
     * @return 结果对象
     */
    public static <T> T parseToken(String token,Class<T> type) {
        if (StringUtil.isEmpty(token)) {
            return null;
        }
        Map<String,Object> body;
        try {
            body = (Map<String,Object>) Jwts.parser()
                    .setSigningKey(JwtConstant.SIGNING_KEY)
                    .parse(token)
                    .getBody();
        } catch (Exception e) {
            e.printStackTrace();
            // 解析失败返回 null
            return null;
        }
        // 解析 token 成功
        T t = ReflectUtil.newInstance(type);
        Set<Map.Entry<String, Object>> entrySet = body.entrySet();
        if (CollectionUtil.isEmpty(entrySet)) {
            return t;
        }
        for (Map.Entry<String, Object> entry : body.entrySet()) {
            Field field = ReflectUtil.getField(type, entry.getKey());
            if (ObjectUtil.isNotNull(field)) {
                ReflectUtil.setFieldValue(t,field,entry.getValue());
            }
        }
        return t;
    }

    /**
     * 获取声明
     * @param object 对象
     * @return 声明
     */
    private static Map<String,Object> getClaims(Object object) {
        Map<String, Object> claims = new HashMap<>();
        Class<?> userClaimsClass = object.getClass();
        Field[] fields = userClaimsClass.getDeclaredFields();
        if (userClaimsClass.isAnnotationPresent(Claim.class)) {
            for (Field field : fields) {
                String name = field.getName();
                Object value = ReflectUtil.getFieldValue(object, field);
                claims.put(name,value);
            }
            return claims;
        }
        for (Field field : fields) {
            if (field.isAnnotationPresent(Claim.class)) {
                String name = field.getName();
                Object value = ReflectUtil.getFieldValue(object, field);
                claims.put(name,value);
            }
        }
        return claims;
    }

}
